#!/usr/bin/python

import unittest, sys, os, os.path as path, struct

if __name__ == "__main__":
    """Hack around the python import system to
    allow us to import from a parent directory"""
    FPATH = path.normpath(path.join(os.getcwd(), __file__))
    IPATH = path.normpath(path.join(path.dirname(FPATH),"../../"))
    sys.path.append(IPATH)

from gehyra.common.ipv6 import IPv6Address as I6


class TestIPv6AddressConstructor(unittest.TestCase):

    def test_valid_integer(self):
        i = I6(1L)
        self.assertEqual(i.ip, 1L)

    def test_integer_min(self):
        i = I6(0L)
        self.assertEqual(i.ip, 0L)

    def test_integer_max(self):
        i = I6(2**128-1L)
        self.assertEqual(i.ip, 2**128-1L)

    def test_negative_integer(self):
        self.assertRaises(ValueError, I6, -1L)

    def test_above_max_integer(self):
        self.assertRaises(ValueError, I6, 2**128L)

    def test_valid_hexstr_with_prefix(self):
        i = I6("0xFEDCBA98FEDCBA98FEDCBA98FEDCBA98")
        self.assertEqual(i.ip, 0xFEDCBA98FEDCBA98FEDCBA98FEDCBA98)

    def test_valid_hexstr_without_prefix(self):
        i = I6("FEDCBA98FEDCBA98FEDCBA98FEDCBA98")
        self.assertEqual(i.ip, 0xFEDCBA98FEDCBA98FEDCBA98FEDCBA98)

    def test_max_hexstr(self):
        i = I6("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
        self.assertEqual(i.ip, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

    def test_min_hexstr(self):
        i = I6("0x00000000000000000000000000000000")
        self.assertEqual(i.ip, 0x00000000000000000000000000000000)

    def test_short_hexstr(self):
        self.assertRaises(ValueError, I6, "00")

    def test_long_hexstr(self):
        self.assertRaises(ValueError, I6, "0x123456781234567812345678123456789")

    def test_common_str(self):
        i = I6("3ffe:1900:4545:3:200:f8ff:fe21:67cf")
        self.assertEqual(i.ip, 0x3FFE1900454500030200F8FFFE2167CF)

    def test_common_str_with_brackets(self):
        i = I6("[3ffe:1900:4545:3:200:f8ff:fe21:67cf]")
        self.assertEqual(i.ip, 0x3FFE1900454500030200F8FFFE2167CF)

    def test_min_common_str(self):
        i = I6("0:0:0:0:0:0:0:0")
        self.assertEqual(i.ip, 0)

    def test_max_common_str(self):
        i = I6("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF")
        self.assertEqual(i.ip, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

    def test_too_few_octets(self):
        self.assertRaises(ValueError, I6, "0:0:0:0:0:0:0")

    def test_octet_invalid(self):
        self.assertRaises(ValueError, I6, "3ffe:1900:4545:3:200:g8ff:fe21:67cf")

    def test_octet_out_of_range(self):
        self.assertRaises(ValueError, I6, "3ffe::3ffff:200:g8ff:fe21:67cf")

    def test_too_many_octets(self):
        self.assertRaises(ValueError, I6, "0:0:0:0:0:0:0:0:0")

    def test_default_interface(self):
        i = I6("::")
        self.assertEqual(i.ip, 0)

    def test_default_loopback(self):
        i = I6("::1")
        self.assertEqual(i.ip, 1L)

    def test_invalid_short_contracted(self):
        self.assertRaises(ValueError, I6, ":")
 
    def test_invalid_long_contracted(self):
        self.assertRaises(ValueError, I6, ":::")

    def test_double_contracted(self):
        self.assertRaises(ValueError, I6, "0::0::1")
 
    # TODO:
    #def test_min_packed(self):
    #    i = I6(struct.pack("!L", 0L))
    #    self.assertEqual(i.ip, 0L)

    #def test_max_packed(self):
    #    i = I6(struct.pack("!L", 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
    #    self.assertEqual(i.ip, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)

    def test_packed_sextets(self):
        s = struct.pack("!HHHHHHHH", 0xA192, 0xF168, 0x0, 0xB1, 0x209, 0x85, 0x143, 0x99)
        # print 
        # print repr(s)
        i = I6(s)
        self.assertEqual(i.ip, 0xA192F168000000B10209008501430099)
        

class TestIPv6Getters(unittest.TestCase):
    
    def test_get_hex_without_prefix_implicit(self):
        i = I6("0xabcdef90abcdef90abcdef90abcdef90")
        self.assertEqual("ABCDEF90ABCDEF90ABCDEF90ABCDEF90", i.get_hex_string())

    def test_get_hex_without_prefix_explicit(self):
        i = I6("0x12345678123456781234567812345678")
        self.assertEqual("12345678123456781234567812345678", i.get_hex_string(False))

    def test_get_hex_with_prefix(self):
        i = I6("0x2468aced2468aced2468aced2468aced")
        self.assertEqual("0x2468ACED2468ACED2468ACED2468ACED", i.get_hex_string(True))
        
    def test_get_common_string_unexpanded_implicit(self):
        i = I6("0000:0001:0020:2000:0000:0001:0020:2000")
        self.assertEqual("0:1:20:2000:0:1:20:2000", i.get_common_string())

    def test_get_common_string_unexpanded_explicit(self):
        i = I6("1:2:3:4:5:6:7:8")
        self.assertEqual("1:2:3:4:5:6:7:8", i.get_common_string(False))

    def test_get_common_string_expanded(self):
        i = I6("0:0:0:0:0:0:0:0")
        self.assertEqual("0000:0000:0000:0000:0000:0000:0000:0000", i.get_common_string(True))

if __name__ == "__main__":
    unittest.main()

